package com.zhiche.wms.service.inbound.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.toolkit.CollectionUtils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.core.supports.enums.TableStatusEnum;
import com.zhiche.wms.domain.mapper.base.StorehouseMapper;
import com.zhiche.wms.domain.mapper.inbound.InboundPutawayHeaderMapper;
import com.zhiche.wms.domain.mapper.inbound.InboundPutawayLineMapper;
import com.zhiche.wms.domain.model.base.StoreLocation;
import com.zhiche.wms.domain.model.base.Storehouse;
import com.zhiche.wms.domain.model.inbound.InboundPutawayHeader;
import com.zhiche.wms.domain.model.inbound.InboundPutawayLine;
import com.zhiche.wms.domain.model.otm.OtmOrderRelease;
import com.zhiche.wms.domain.model.stock.Stock;
import com.zhiche.wms.domain.model.stock.StockProperty;
import com.zhiche.wms.dto.inbound.InboundPutawayDTO;
import com.zhiche.wms.dto.inbound.LocChangeDTO;
import com.zhiche.wms.service.base.IStoreLocationService;
import com.zhiche.wms.service.inbound.IInboundPutawayLineService;
import com.zhiche.wms.service.otm.IOtmOrderReleaseService;
import com.zhiche.wms.service.stock.IStockService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.*;

@Service
public class InboundPutawayLineServiceImpl extends ServiceImpl<InboundPutawayLineMapper, InboundPutawayLine> implements IInboundPutawayLineService {
    @Autowired
    private IStockService stockService;
    @Autowired
    private IOtmOrderReleaseService releaseService;
    @Autowired
    private IStoreLocationService locationService;
    @Autowired
    InboundPutawayHeaderMapper inboundPutawayHeaderMapper;
    @Autowired
    StorehouseMapper storehouseMapper;

    private final Logger LOGGER = LoggerFactory.getLogger(getClass());

    public InboundPutawayDTO getPutWaylineById(Long id) {
        InboundPutawayDTO inboundPutawayDTO = null;
        try {
            inboundPutawayDTO = this.baseMapper.getPutWayByLineId(id);
        } catch (BaseException e) {
            LOGGER.error("Service:\t" + e.toString());
            throw new BaseException("查询入库信息出错");
        } catch (Exception e) {
            LOGGER.error("Service:\t" + e.toString());
            throw new BaseException("查询出库信息出错");
        }
        return inboundPutawayDTO;
    }

    public Page<InboundPutawayDTO> queryLinePage(Page<InboundPutawayDTO> page) {
        Map<String, Object> condition = page.getCondition();
        if (condition != null && !condition.isEmpty()) {
            EntityWrapper<InboundPutawayDTO> ew = buildCondition(condition);
            List<InboundPutawayDTO> inboundPutawayDTOS = this.baseMapper.queryPutWayListByPage(page, ew);
            if (CollectionUtils.isNotEmpty(inboundPutawayDTOS)) {
                page.setRecords(inboundPutawayDTOS);
            }
        }
        return page;
    }

    private EntityWrapper<InboundPutawayDTO> buildCondition(Map<String, Object> condition) {
        EntityWrapper<InboundPutawayDTO> ew = new EntityWrapper<>();
        Object vinNO = condition.get("vinNo");
        Object materielId = condition.get("materielId");
        Object startDate = condition.get("startDate");
        Object endDate = condition.get("endDate");
        Object houseId = condition.get("houseId");
        if (!Objects.isNull(materielId)) ew.like("materiel_id", materielId.toString());
        if (!Objects.isNull(houseId)) ew.eq("store_house_id", houseId.toString());
        if (startDate != null && StringUtils.isNotBlank(startDate.toString())) {
            ew.ge("gmt_create", startDate);
        }
        if (endDate != null && StringUtils.isNotBlank(endDate.toString())) {
            ew.le("gmt_create", endDate);
        }
        if (condition.get("keyStatus") != null && StringUtils.isNotBlank(condition.get("keyStatus").toString())) {
            ew.eq("key_status", condition.get("keyStatus").toString());
        }
        if (!Objects.isNull(vinNO)) {
            String vin = vinNO.toString();
            String[] split = vin.split(",");
            List<String> vins = Arrays.asList(split);
            ew.andNew().in("lot_no1", vins).or().like("lot_no1", vin);
        }
        ew.orderBy("id", false);
        return ew;
    }

    @Override
    public List<InboundPutawayDTO> queryExportData(Map<String, String> condition) {
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        if (StringUtils.isBlank(condition.get("houseId"))) {
            throw new BaseException("仓库信息不能为空");
        }
        EntityWrapper<InboundPutawayDTO> ew = new EntityWrapper<>();
        ew.eq("store_house_id", condition.get("houseId"));

        if (StringUtils.isNotBlank(condition.get("materielId"))) {
            ew.like("materiel_id", condition.get("materielId"));
        }
        if (StringUtils.isNotBlank(condition.get("keyStatus"))) {
            ew.eq("key_status", condition.get("keyStatus"));
        }
        if (StringUtils.isNotBlank(condition.get("startDate"))) {
            ew.ge("gmt_create", condition.get("startDate"));
        }
        if (StringUtils.isNotBlank(condition.get("endDate"))) {
            ew.le("gmt_create", condition.get("endDate"));
        }
        if (StringUtils.isNotBlank(condition.get("vinNo"))) {
            String vin = condition.get("vinNo").toString();
            List<String> vins = Arrays.asList(vin.split(","));
            ew.andNew().in("lot_no1", vins).or().like("lot_no1", vin);
        }
        ew.orderBy("id", false);
        return baseMapper.selectExportData(ew);
    }

    /**
     * 领取钥匙时获取信息
     */
    @Override
    public InboundPutawayDTO getReceiveKeyInfo(Map<String, String> condition) {
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        String lotNo1 = condition.get("lotNo1");
        String houseId = condition.get("houseId");
        if (StringUtils.isBlank(lotNo1)) {
            throw new BaseException("车架号信息不能为空");
        }
        if (StringUtils.isBlank(houseId)) {
            throw new BaseException("仓库id不能为空");
        }
        EntityWrapper<OtmOrderRelease> oorEW = new EntityWrapper<>();
        oorEW.eq("qr_code", lotNo1)
                .ne("status", TableStatusEnum.STATUS_50.getCode())
                .orderBy("id", false);
        OtmOrderRelease release = releaseService.selectOne(oorEW);
        if (release != null) {
            lotNo1 = release.getVin();
        }
        // 查询入库信息
        EntityWrapper<InboundPutawayLine> ew = new EntityWrapper<>();
        ew.eq("lot_no1", lotNo1)
                .eq("storeHouseId", houseId)
                .orderBy("gmt_create", false)
                .orderBy("id", false);
        List<InboundPutawayDTO> result = this.baseMapper.getLineWithHouseId(ew);
        if (CollectionUtils.isEmpty(result)) {
            throw new BaseException("未查询到车架号:" + lotNo1 + "入库信息");
        }
        if (result.size() > 1) {
            throw new BaseException("查询到车架号:" + lotNo1 + "多条入库");
        }
        InboundPutawayDTO putawayDTO = result.get(0);
        //获取调整后最终库位信息
        StockProperty property = new StockProperty();
        property.setOwnerId(putawayDTO.getOwnerId());
        property.setMaterielId(putawayDTO.getMaterielId());
        property.setLotNo1(putawayDTO.getLotNo1());
        property.setStoreHouseId(putawayDTO.getStoreHouseId());
        property.setUom(putawayDTO.getUom());
        List<Stock> stockList = stockService.queryStockList(property);
        if (CollectionUtils.isEmpty(stockList)) {
            throw new BaseException("未查询到对应库存信息");
        }
        Stock stock = stockList.get(0);
        StoreLocation location = locationService.selectLocationByLocationId(stock.getLocationId());
        if (location != null) {
            putawayDTO.setAreaCode(location.getStoreAreaName());
            putawayDTO.setAreaName(location.getStoreAreaName());
            putawayDTO.setLocationCode(location.getCode());
            putawayDTO.setLocationName(location.getName());
        }
        return putawayDTO;
    }

    /**
     * 领取钥匙
     */
    @Override
    public void updateReceiveKey(Map<String, String> condition) {
        if (condition == null || condition.isEmpty() || !condition.containsKey("putawayLineIds")) {
            throw new BaseException("参数不能为空");
        }

        String putawayLineIds = condition.get("putawayLineIds");
        if (StringUtils.isBlank(putawayLineIds)) {
            throw new BaseException("入库明细参数不为空");
        }

        List<String> messages = new ArrayList<>();
        String[] LineIds = putawayLineIds.split(",");
        for (String putawayLineId : LineIds) {

            InboundPutawayLine line = selectById(Long.valueOf(putawayLineId));
            if (TableStatusEnum.STATUS_20.getCode().equals(line.getKeyStatus())) {
                messages.add(line.getLotNo1() + "已经领取钥匙");
                continue;
            }
            InboundPutawayLine newLine = new InboundPutawayLine();
            newLine.setId(line.getId());
            newLine.setKeyStatus(TableStatusEnum.STATUS_20.getCode());
            updateById(newLine);
        }

        if (messages.size() > 0) {
            String message = "";
            for (String s : messages) {
                message += s + ",";
            }
            throw new BaseException(1,message);
        }


    }

    /**
     * 领取钥匙时打印二维码
     */
    @Override
    public InboundPutawayDTO getKeyPrintInfo(Map<String, String> condition) {
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        String lotNo1 = condition.get("lotNo1");
        if (StringUtils.isBlank(lotNo1)) {
            throw new BaseException("车架号信息不能为空");
        }
        String img = null;
        try {
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            Hashtable<EncodeHintType, String> hints = new Hashtable<>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            BitMatrix bitMatrix = multiFormatWriter.encode(lotNo1, BarcodeFormat.QR_CODE, 60, 60, hints);
            BufferedImage image = InboundNoticeLineServiceImpl.toBufferedImage(bitMatrix);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(image, "png", os);
            //Base64 base64 = new Base64();
            BASE64Encoder base64 = new BASE64Encoder();
            img = base64.encode(os.toByteArray());
        } catch (Exception e) {
            LOGGER.error("InboundPutawayLineServiceImpl.getKeyPrintInfo:[ERROR]" + e.toString());
            throw new BaseException("生成二维码错误");
        }
        InboundPutawayDTO putawayDTO = new InboundPutawayDTO();
        putawayDTO.setImgBase64(img);
        putawayDTO.setLotNo1(lotNo1);
        return putawayDTO;
    }

    /**
     * 查询调整记录
     */
    @Override
    public Page<LocChangeDTO> queryChangLocList(Page<LocChangeDTO> page) {
        if (page == null) {
            throw new BaseException("分页参数不能为空");
        }
        Map<String, Object> condition = page.getCondition();
        EntityWrapper<LocChangeDTO> ew = buildLocListCondition(condition);
        List<LocChangeDTO> rec = baseMapper.queryChangeLocList(page, ew);
        page.setRecords(rec);
        return page;
    }

    /**
     * 导出调整记录
     */
    @Override
    public List<LocChangeDTO> queryExportLocList(Map<String, Object> condition) {
        EntityWrapper<LocChangeDTO> ew = buildLocListCondition(condition);
        return baseMapper.queryExportLocList(ew);
    }

    @Override
    public boolean queryKeyStatus(Map<String, String> condition) {
        if (StringUtils.isEmpty(condition.get("vin"))) {
            throw new BaseException("车架号为空");
        }
        Wrapper<InboundPutawayLine> ew = new EntityWrapper<>();
        ew.eq("ipl.lot_no1", condition.get("vin"));
        ew.eq("ws.id", "10014");
        ew.orderBy("ipl.gmt_modified", false);
        List<InboundPutawayLine> inboundPutawayLine = baseMapper.queryKeyStatus(ew);
        if (CollectionUtils.isEmpty(inboundPutawayLine)) {
            throw new BaseException("未找到【" + condition.get("vin") + "】车架号对应的信息");
        }
        if (TableStatusEnum.STATUS_20.getCode().equals(inboundPutawayLine.get(0).getKeyStatus())) {
            return true;
        }
        return false;
    }


    private EntityWrapper<LocChangeDTO> buildLocListCondition(Map<String, Object> condition) {
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        Object houseId = condition.get("houseId");
        if (houseId == null || StringUtils.isBlank(houseId.toString())) {
            throw new BaseException("仓库id不能为空");
        }
        EntityWrapper<LocChangeDTO> ew = new EntityWrapper<>();
        ew.eq("store_house_id", condition.get("houseId").toString());

        if (condition.get("ownerId") != null && StringUtils.isNotBlank(condition.get("ownerId").toString())) {
            ew.eq("owner_id", condition.get("ownerId").toString());
        }
        if (condition.get("startDate") != null && StringUtils.isNotBlank(condition.get("startDate").toString())) {
            ew.ge("gmt_create", condition.get("startDate").toString());
        }
        if (condition.get("endDate") != null && StringUtils.isNotBlank(condition.get("endDate").toString())) {
            ew.le("gmt_create", condition.get("endDate").toString());
        }
        if (condition.get("lotNo1") != null && StringUtils.isNotBlank(condition.get("lotNo1").toString())) {
            String vin = condition.get("lotNo1").toString();
            String[] split = vin.split(",");
            List<String> vins = Arrays.asList(split);
            ew.andNew().in("lot_no1", vins).or().like("lot_no1", vin);
        }
        ew.orderBy("lot_no1").orderBy("gmt_create");
        return ew;
    }
}